package com.yiba.vpn.service;

import com.yiba.vpn.authorization.manager.TokenManager;
import com.yiba.vpn.domain.EmailSendRecord;
import com.yiba.vpn.domain.EmailSeting;
import com.yiba.vpn.repository.EmailSettingRepository;
import com.yiba.vpn.repository.SendEmailRecordRepository;
import com.yiba.vpn.util.AccordEypeSelectWhichEmailWlUtils;
import com.yiba.vpn.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.Map.Entry;

/**
 * 邮箱服务
 *
 * @author : zhangws
 */
@Service
public class EmailProcessService {

    private static Logger logger = LoggerFactory.getLogger(EmailProcessService.class);

    @Autowired
    private SendEmailRecordRepository sendEmailRecordRepository;

    @Autowired
    private EmailSettingRepository emailSettingRepository;

    @Autowired
    private TokenManager tokenManager;


    //根据邮箱类型gmail QQ 网易 进行对应的匹配 单个账号一小时内最高发送40次 一天最多发送400份
    public Map<String, String> sendEmailLimitByAccount(String toemamil, String subject, String content, Integer etype) {
        //根据etype 获取对应的邮箱集合
        List<EmailSeting> fromEmails = emailSettingRepository.findByEtype(etype);
        Date currentDate = new Date();
        Map<String, String> result = new HashMap<>();

        if (fromEmails == null || fromEmails.size() < 1) {
            //数据库没有对应的邮箱账号信息
            logger.error("数据库没有对应的邮箱账号信息 " + etype);
        } else {
            //轮询获取最适合的邮箱账号 
            EmailSeting fromuser = accordEmailAccountGetSelector(fromEmails, currentDate);
            if (fromuser == null) {
                logger.error(" 类型为 " + etype + " ; 没有找到合适的邮箱 ！");
            } else {
                logger.info("通过轮询策略 选的邮箱账号为 : " + fromuser.getEmail());
                result.put("通过轮询策略 选的邮箱账号为 : ", fromuser.getEmail());
            }

            try {
                AccordEypeSelectWhichEmailWlUtils.accordEtypeSend(fromuser.getEmail(), fromuser.getPwd(), toemamil, subject, content, etype.intValue());
                EmailSendRecord record = new EmailSendRecord();
                record.setEmail(fromuser.getEmail());
                record.setToemail(toemamil);
                sendEmailRecordRepository.save(record);
                long dtimes = tokenManager.incr(fromuser.getEmail() + "_" + DateUtil.parsedate(currentDate, DateUtil.YYYYMMDDx), 43200);
                long htimes = tokenManager.incr(fromuser.getEmail() + "-" + DateUtil.parsedate(currentDate, DateUtil.YYYYMMDDHH), 3600);

                result.put("result : ", "发送成功 日发送次数 ：" + dtimes + "次 ; 时发送次数为 ：" + htimes + " 次！");
            } catch (Exception e) {
                logger.error("邮箱账号 " + fromuser.getEmail() + " 发送邮件出错 " + e.getMessage());
                result.put("result : ", e.getMessage());
            }

        }
        return result;

    }

    // 根据邮箱集合 获取最优的邮箱
    private EmailSeting accordEmailAccountGetSelector(List<EmailSeting> fromEmails, Date currentDate) {
        Iterator<EmailSeting> it = fromEmails.iterator();
        Map<String, EmailSeting> email = new HashMap<>();
        Map<String, Long> availableEmail = new HashMap<>();
        while (it.hasNext()) {
            //从redis中获取当前小时 当前天已经发送的邮件数  如果为空(要么是0 要么走数据库查)
            //如果当天发送的邮件数小于限定值 保存到备选列表 否则不保存
            EmailSeting seting = it.next();

            Long numdx = tokenManager.getInValue(seting.getEmail() + "_" + DateUtil.parsedate(currentDate, DateUtil.YYYYMMDDx));

            Long numhx = tokenManager.getInValue(seting.getEmail() + "-" + DateUtil.parsedate(currentDate, DateUtil.YYYYMMDDHH));

            //只要没超过 限制就放进去轮询
            if (numdx < 450 && numhx < 40) {
                availableEmail.put(seting.getEmail(), numhx);
            }
            email.put(seting.getEmail(), seting);
        }

        //从map中获取发送最少的那个邮箱发送邮件
        return availableEmail == null ? null : email.get(getMinValue(availableEmail));
    }

    public static String getMinValue(Map<String, Long> map) {
        //将map<String,String> 转化为ArryList,但list里面的元素为Entry<String,String>
        List<Entry<String, Long>> list = new ArrayList<Map.Entry<String, Long>>(map.entrySet());
        Collections.sort(list, new Comparator<Entry<String, Long>>() {
            @Override
            public int compare(Entry<String, Long> o1,
                               Entry<String, Long> o2) {
                int flag = o1.getValue().compareTo(o2.getValue());
                if (flag == 0) {
                    return o1.getKey().compareTo(o2.getKey());
                }
                return flag;
            }
        });
        //遍历list得到map里面排序后的元素
        for (Entry<String, Long> en : list) {
            System.out.println(en.getKey() + " " + en.getValue());
        }

        return list.get(0) != null ? list.get(0).getKey() : null;

    }

    public static void main(String[] args) {
        System.out.println(DateUtil.parsedate(new Date(), DateUtil.YYYYMMDDx + "  " + 3600 * 12));

        System.out.println(DateUtil.parsedate(new Date(), DateUtil.YYYYMMDDHH));


    }

}
